package de.tabuma.formcreator.formstructur.logik;

import de.tabuma.formcreator.formstructur.logik.FormStructurWithAttributeFactory;
import de.tabuma.formcreator.entity.*;
import de.tabuma.soap.entity.*;
import de.tabuma.soap.entity.wsdl.*;
import de.tabuma.soap.entity.xsd.*;
import de.tabuma.soap.logik.*;

import java.util.*;
import java.util.logging.*;

/**
  * @author $Author: $
  * @version $Revision: $
  * @since $Date: $
 */
public class FormStructurWithComplexTypeFactory {

    private static final Logger log = Logger.getLogger(FormStructurWithComplexTypeFactory.class.getName());

    public static FormStructur createFormularStruktur(TDefinitions wsdl, XsComplexType xsComplexType, String name, int minocc,int maxocc) {
        FormStructur formularStruktur = new FormStructur(name,xsComplexType.getName(),minocc,maxocc,false, false, false, false);
        List<Long> list = xsComplexType.getXsSimpleContentOrXsComplexContentOrXsAllOrXsChoiceOrXsSequenceOrXsGroupOrXsAttributeOrXsAttributeGroupOrXsAnyAttribute();
        for(int i=0;i<list.size();i++) {
            AnyElement anyElement = PMF.get(list.get(i), new AnyElement());
            Object objekt = anyElement.toObject();
            if(XsSimpleContent.class.isInstance(objekt)) {
                XsSimpleContent xsSimpleContent = (XsSimpleContent) objekt;
                FormStructur formularStruktur1 = createFormularStruktur(wsdl, xsSimpleContent);
                formularStruktur.addFormularStruktur(formularStruktur1);
            }
            else if(XsComplexContent.class.isInstance(objekt)) {
                XsComplexContent xsComplexContent = (XsComplexContent) objekt;
                List<FormStructur> formularStruktur1 = createFormularStruktur(wsdl, xsComplexContent);
                formularStruktur.addFormularStruktur(formularStruktur1);
            }
            else if(XsAll.class.isInstance(objekt)) {
                XsAll xsAll = (XsAll) objekt;
                List<FormStructur> formularStruktur1 = createFormularStruktur(wsdl, xsAll);
                formularStruktur.addFormularStruktur(formularStruktur1);
            }
            else if(XsSequence.class.isInstance(objekt)) {
                XsSequence xsSequence = (XsSequence) objekt;
                FormStructur formularStruktur1 = createFormularStruktur1(wsdl, xsSequence,1,1);
                formularStruktur.addFormularStruktur(formularStruktur1);
            }
            else if(XsChoice.class.isInstance(objekt)) {
                XsChoice xsChoice = (XsChoice) objekt;
                FormStructur formularStruktur1 = createFormularStruktur3(wsdl, xsChoice);
                formularStruktur.addFormularStruktur(formularStruktur1);
            }
            else if(XsGroup.class.isInstance(objekt)) {
                XsGroup xsGroup = (XsGroup) objekt;
                FormStructur formularStruktur1 = createFormularStruktur4(wsdl, xsGroup);
                formularStruktur.addFormularStruktur(formularStruktur1);
            }
            else if(XsAttribute.class.isInstance(objekt)) {
                XsAttribute xsAttribute = (XsAttribute) objekt;
                FormStructur formularStruktur1 = FormStructurWithAttributeFactory.createFormularStruktur(wsdl, xsAttribute);
                formularStruktur.addFormularStruktur(formularStruktur1);
            }
            else if(XsAttributeGroup.class.isInstance(objekt)) {
                XsAttributeGroup xsAttributeGroup = (XsAttributeGroup) objekt;
                List<FormStructur> formularStruktur1 = FormStructurWithAttributeFactory.createFormularStruktur(wsdl, xsAttributeGroup);
                formularStruktur.addFormularStruktur(formularStruktur1);
            }
        }
        return formularStruktur;
    }

    public static FormStructur createFormularStruktur(TDefinitions wsdl, XsSimpleContent xsSimpleContent) {
        return null;
    }

    public static List<FormStructur> createFormularStruktur(TDefinitions wsdl, XsComplexContent xsComplexContent) {
        ArrayList<FormStructur> list = new ArrayList<FormStructur>();
        int max = xsComplexContent.getXsRestrictionOrXsExtension().size()>1?1:xsComplexContent.getXsRestrictionOrXsExtension().size();
        for(int i=0;i<max;i++) {
            AnyElement anyElement = PMF.get(xsComplexContent.getXsRestrictionOrXsExtension().get(i), new AnyElement());
            Object object = anyElement.toObject();
            if(XsRestriction.class.isInstance(object)) {
                XsRestriction xsRestriction = (XsRestriction) object;
                List<FormStructur> ergebnis = createFormularStruktur(wsdl, xsRestriction);
                if(ergebnis!=null) {
                    list.addAll(ergebnis);
                }
            }
            else if(XsExtension.class.isInstance(object)) {
                XsExtension xsExtension = (XsExtension) object;
                List<FormStructur> ergebnis = createFormularStruktur(wsdl, xsExtension);
                if(ergebnis!=null) {
                    list.addAll(ergebnis);
                }
            }
        }
        return list;
    }

    public static List<FormStructur> createFormularStruktur(TDefinitions wsdl,XsRestriction xsRestriction) {
        ArrayList<FormStructur> list = new ArrayList<FormStructur>();
        for(int i=0;i<xsRestriction.getXsAllOrXsChoiceOrXsSequenceOrXsGroupOrXsSimpleTypeOrXsMinInclusiveOrXsMinExclusiveOrXsMaxInclusiveOrXsMaxExclusiveOrXsTotalDigitsOrXsFractionDigitsOrXsPatternOrXsEnumerationOrXsWhiteSpaceOrXsLengthOrXsMaxLengthOrXsMinLength().size();i++) {
            Object objekt = xsRestriction.getXsAllOrXsChoiceOrXsSequenceOrXsGroupOrXsSimpleTypeOrXsMinInclusiveOrXsMinExclusiveOrXsMaxInclusiveOrXsMaxExclusiveOrXsTotalDigitsOrXsFractionDigitsOrXsPatternOrXsEnumerationOrXsWhiteSpaceOrXsLengthOrXsMaxLengthOrXsMinLength().get(i);
            if(XsAll.class.isInstance(objekt)) {
                XsAll xsAll = (XsAll) objekt;
                List<FormStructur> list1 = createFormularStruktur(wsdl, xsAll);
                if(list1!=null) {
                    list.addAll(list1);
                }
            }
            else if(XsChoice.class.isInstance(objekt)) {
                XsChoice xsChoice = (XsChoice) objekt;
                FormStructur fs = createFormularStruktur3(wsdl, xsChoice);
                if(fs!=null) {
                    list.add(fs);
                }
            }
            else if(XsSequence.class.isInstance(objekt)) {
                XsSequence xsSequence = (XsSequence) objekt;
                //TODO Klärung der Zusammenhänge zwischen XsRestriction und XsSequence
                FormStructur fs = createFormularStruktur1(wsdl, xsSequence, 1, 1);
                if(fs!=null) {
                    list.add(fs);
                }
            }
            else if(XsGroup.class.isInstance(objekt)) {
                XsGroup xsGroup = (XsGroup) objekt;
                FormStructur fs = createFormularStruktur4(wsdl, xsGroup);
                if(fs!=null) {
                    list.add(fs);
                }
            }
            else if(XsSimpleType.class.isInstance(objekt)) {
                XsSimpleType xsSimpleType = (XsSimpleType) objekt;
                //TODO Definition was passiert wenn es sich um ein SimpleType handelt
            }
            else if(XsMinInclusive.class.isInstance(objekt)) {
                XsMinInclusive xsMinInclusive = (XsMinInclusive) objekt;
                //TODO Definition was passiert, wenn es sich um ein XsMinInclusive handelt
            }
            else if(XsMaxInclusive.class.isInstance(objekt)) {
                //TODO Definition was passiert, wenn es sich um ein XsMaxInclusive handelt
            }
            else if(XsMinExclusive.class.isInstance(objekt)) {
                //TODO Definition was passiert, wenn es sich um ein XsMinExclusive handelt
            }
            else if(XsMaxExclusive.class.isInstance(objekt)) {
                //TODO Definition was passiert, wenn es sich um ein XsMaxExclusive handelt
            }
            else if(XsTotalDigits.class.isInstance(objekt)) {
                //TODO Definition was passiert, wenn es sich um ein XsTotalDigits handelt
            }
            else if(XsFractionDigits.class.isInstance(objekt)) {
                //TODO Definition was passiert, wenn es sich um ein XsFractionDigits handelt
            }
            else if(XsPattern.class.isInstance(objekt)) {
                //TODO Definition was passiert, wenn es sich um ein XsPattern handelt
            }
            else if(XsWhitespace.class.isInstance(objekt)) {
                //TODO Definition was passiert, wenn es sich um ein XsWhiteSpace handelt
            }
            else if(XsLength.class.isInstance(objekt)) {
                //TODO Definition was passiert, wenn es sich um ein XsLength handelt
            }
            else if(XsMaxLength.class.isInstance(objekt)) {
                //TODO Definition was passiert, wenn es sich um ein XsMaxLength handelt
            }
            else if(XsMinLength.class.isInstance(objekt)) {
                //TODO Definition was passiert, wenn es sich um ein MsMinLength handelt
            }
        }
        for(int i=0;i<xsRestriction.getXsAttributeOrXsAttributeGroup().size();i++) {
            AnyElement anyElement = PMF.get(xsRestriction.getXsAttributeOrXsAttributeGroup().get(i), new AnyElement());
            Object object = anyElement.toObject();
            if(XsAttribute.class.isInstance(object)) {
                XsAttribute xsAttribute = (XsAttribute) object;
                FormStructur fs = FormStructurWithAttributeFactory.createFormularStruktur(wsdl, xsAttribute);
                if(fs!=null) {
                    list.add(fs);
                }
            }
            else if(XsAttributeGroup.class.isInstance(object)) {
                XsAttributeGroup xsAttributeGroup = (XsAttributeGroup) object;
                List<FormStructur> list1 = FormStructurWithAttributeFactory.createFormularStruktur(wsdl, xsAttributeGroup);
                if(list1!=null) {
                    list.addAll(list1);
                }
            }
        }
        return list;
    }

    public static List<FormStructur> createFormularStruktur(TDefinitions wsdl,XsExtension xsExtension) {
        return null;
    }

    public static List<FormStructur> createFormularStruktur(TDefinitions wsdl, XsAll xsAll) {
        ArrayList<FormStructur> list = new ArrayList<FormStructur>();
        for(int i=0;i<xsAll.getXsElement().size();i++) {
            XsElement xsElement = PMF.get(xsAll.getXsElement().get(i), new XsElement());
            FormStructur formularElement = createFormularStruktur2(wsdl, xsElement,3);
            if(formularElement!=null) {
                list.add(formularElement);
            }
        }
        return list;
    }

    public static FormStructur createFormularStruktur2(TDefinitions wsdl, XsElement xsElement, int type) {
        int minOccurs = 1;
        if(xsElement.getMinOccurs()!=null) {
            if(!xsElement.getMinOccurs().equals("")) {
                minOccurs = Integer.valueOf(xsElement.getMinOccurs());
            }
        }
        if(minOccurs>0 && type==2) {//XSD:CHOICE
            minOccurs = 0;
        }
        int maxOccurs = 1;
        if(xsElement.getMaxOccurs()!=null) {
            if(xsElement.getMaxOccurs().equals("unbounded")) {
                maxOccurs = -1;
            }
            else {
                if(!xsElement.getMaxOccurs().equals("")) {
                    maxOccurs = Integer.valueOf(xsElement.getMaxOccurs());
                }
            }
        }
        if(maxOccurs>1 && type==3) {//XSD:ALL Element
            maxOccurs = 1;
        }
        xsElement.setMinOccurs(""+minOccurs);
        xsElement.setMaxOccurs(""+maxOccurs);
        String elementType = xsElement.getType();
        int index = elementType.lastIndexOf(':');
        if(index!=-1) {
            elementType = elementType.substring(index+1,elementType.length());
        }

        
        FormStructur formularStruktur = new FormStructur(xsElement.getName(), elementType, minOccurs, maxOccurs, false, false, false, false);
        formularStruktur = setDescriptionToFormStructur(formularStruktur,xsElement.getXsAnnotationId());
        if(formularStruktur.isSimpleType()) {
            return formularStruktur;
        }
        else {
            return createFormularStrukturAsComplexType(wsdl, xsElement);
        }
    }

    public static FormStructur setDescriptionToFormStructur(FormStructur formStructur, Long annotationId) {
        if(annotationId!=null && annotationId!=0) {
            XsAnnotation xsAnnotation = PMF.get(annotationId, new XsAnnotation());
            if(xsAnnotation!=null) {
                if(xsAnnotation.getXsAppinfoOrXsDocumentation()!=null) {
                    List object = xsAnnotation.getXsAppinfoOrXsDocumentation();
                    for(int i=0;i<object.size();i++) {
                        AnyElement any = (AnyElement) PMF.get((Long) object.get(i),new AnyElement());
                        Object obj = any.toObject();
                        if(obj instanceof XsDocumentation) {
                            XsDocumentation xsDocumentation = (XsDocumentation) obj;
                            if(xsDocumentation.getContent()!=null) {
                                formStructur.setDescription(xsDocumentation.getContent());
                            }
                        }
                        if(obj instanceof XsAppInfo) {
                            XsAppInfo xsAppInfo = (XsAppInfo) obj;
                            if(xsAppInfo.getContent()!=null) {
                                formStructur.setDescription(xsAppInfo.getContent());
                            }
                        }
                    }
                }
            }
        }
        return formStructur;
    }

    public static FormStructur createFormularStruktur1(TDefinitions wsdl, XsSequence xsSequence,int minOccurs, int maxOccurs) {
        FormStructur formularStruktur = new FormStructur("Sequenz", "XsSequence", minOccurs, maxOccurs, false, true, false, false);
        for(int i=0;i<xsSequence.getXsElementOrXsGroupOrXsChoiceOrXsSequenceOrXsAny().size();i++) {
            AnyElement anyElement = PMF.get(xsSequence.getXsElementOrXsGroupOrXsChoiceOrXsSequenceOrXsAny().get(i), new AnyElement());
            Object object = anyElement.toObject();
            if(XsElement.class.isInstance(object)) {
                XsElement xsElement = (XsElement) object;
                FormStructur formularStruktur1 = createFormularStruktur2(wsdl, xsElement, 1);
                if(formularStruktur1!=null) {
                    formularStruktur.addFormularStruktur(formularStruktur1);
                }
            }
            else if(XsGroup.class.isInstance(object)) {
                XsGroup xsGroup = (XsGroup) object;
                FormStructur formularStruktur1 = createFormularStruktur4(wsdl, xsGroup);
                if(formularStruktur1!=null) {
                    formularStruktur.addFormularStruktur(formularStruktur1);
                }
            }
            else if(XsChoice.class.isInstance(object)) {
                XsChoice xsChoice = (XsChoice) object;
                FormStructur formularStruktur1 = createFormularStruktur3(wsdl, xsChoice);
                if(formularStruktur1!=null) {
                    formularStruktur.addFormularStruktur(formularStruktur1);
                }
            }
            else if(object instanceof XsSequence) {
                XsSequence xsSequence1 = (XsSequence) object;
                FormStructur formularStruktur1 = createFormularStruktur1(wsdl, xsSequence1,1,1);
                if(formularStruktur1!=null) {
                    formularStruktur.addFormularStruktur(formularStruktur1);
                }
            }
        }
        return formularStruktur;
    }

    public static FormStructur createFormularStruktur3(TDefinitions wsdl, XsChoice xsChoice) {
        FormStructur formularStruktur = new FormStructur("Auswahl", "xsChoice", 1, 1, false, false, true, false);
        return formularStruktur;
    }

    public static FormStructur createFormularStruktur4(TDefinitions wsdl, XsGroup xsGroup) {
        return null;
    }

    public static FormStructur createFormularStrukturAsComplexType(TDefinitions wsdl,XsElement xsElement) {
        List<XsSchema> list = SchemaFacade.getSchema(wsdl);
        List<XsComplexType> complexTypeList = SoapFacade.getComplexType(list);
        for(int i=0;i<complexTypeList.size();i++) {

            XsComplexType xsComplexType = complexTypeList.get(i);
            String elementType = xsElement.getType();
            int index = elementType.lastIndexOf(':');
            if(index!=-1) {
                elementType = elementType.substring(index+1, elementType.length());
            }
            if(xsComplexType.getName().equals(elementType)) {

                int minOccurs = 1;
                if(xsElement.getMinOccurs()!=null) {
                    if(!xsElement.getMinOccurs().equals("")) {
                        minOccurs = Integer.valueOf(xsElement.getMinOccurs());
                    }
                }
                int maxOccurs = 1;
                if(xsElement.getMaxOccurs()!=null) {
                    if(!xsElement.getMaxOccurs().equals("")) {
                        maxOccurs = Integer.valueOf(xsElement.getMaxOccurs());
                    }
                }

                return createFormularStruktur(wsdl, xsComplexType, xsElement.getName(), minOccurs, maxOccurs);
            }
        }
        return null;
    }


}
